# -*- coding:utf-8 -*-

import os
import socket
from datetime import datetime
from fastapi import UploadFile, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession

from module_admin.dao.server_host_dao import ServerHostDao
from module_admin.entity.vo.agent_file_vo import AgentFileUploadResponse
from utils.log_util import logger
from config.env import AppConfig


class AgentFileService:
    """Agent文件服务（简化版）"""
    
    # Agent文件存储目录
    AGENT_FILES_DIR = os.path.join(os.getcwd(), "agent_files")
    
    @classmethod
    def _get_server_internal_ip(cls) -> str:
        """获取服务器内网IP"""
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            s.connect(("8.8.8.8", 80))
            local_ip = s.getsockname()[0]
            s.close()
            logger.info(f"获取服务器内网IP: {local_ip}")
            return local_ip
        except Exception as e:
            logger.warning(f"无法获取服务器IP: {e}，使用 localhost")
            return "localhost"
    
    @classmethod
    def _ensure_agent_files_dir(cls):
        """确保Agent文件目录存在"""
        if not os.path.exists(cls.AGENT_FILES_DIR):
            os.makedirs(cls.AGENT_FILES_DIR, exist_ok=True)
            logger.info(f"创建Agent文件目录: {cls.AGENT_FILES_DIR}")
    
    @classmethod
    async def upload_agent_file(
        cls,
        db: AsyncSession,
        file: UploadFile
    ) -> AgentFileUploadResponse:
        """
        上传Agent文件（简化版：无token，依赖IP验证）
        """
        cls._ensure_agent_files_dir()
        
        # 验证文件类型
        if not file.filename.endswith('.tar.gz'):
            raise Exception("只支持 .tar.gz 格式的文件")
        
        # 生成唯一文件名（带时间戳）
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        filename = f"agent_{timestamp}.tar.gz"
        file_path = os.path.join(cls.AGENT_FILES_DIR, filename)
        
        # 保存文件
        try:
            with open(file_path, "wb") as f:
                content = await file.read()
                f.write(content)
            
            file_size = os.path.getsize(file_path)
            logger.info(f"Agent文件上传成功: {filename} ({file_size} bytes)")
            
            # 获取服务器内网IP并构造下载URL
            internal_ip = cls._get_server_internal_ip()
            download_url = f"http://{internal_ip}:{AppConfig.app_port}{AppConfig.app_root_path}/agent-files/download/{filename}"
            logger.info(f"生成下载URL: {download_url}")
            
            return AgentFileUploadResponse(
                file_name=filename,
                file_size=file_size,
                file_path=file_path,
                download_url=download_url,
                download_token="",  # 不再使用token
                expires_in=0  # 不再有过期时间
            )
            
        except Exception as e:
            # 失败时删除文件
            if os.path.exists(file_path):
                os.remove(file_path)
            raise Exception(f"文件保存失败: {str(e)}")
    
    @classmethod
    async def verify_ip_in_server_hosts(cls, db: AsyncSession, client_ip: str) -> bool:
        """
        验证请求IP是否在server_host表中
        检查host_ip和internal_ip两个字段
        
        ✅ 直接查询IP，避免lazy loading触发greenlet错误
        """
        from sqlalchemy import select, or_
        from module_admin.entity.do.server_host_do import ServerHost
        
        # ✅ 直接查询IP字段，不加载完整对象，避免greenlet上下文问题
        result = await db.execute(
            select(ServerHost.host_name).where(
                ServerHost.del_flag == '0',
                ServerHost.status == '0',
                or_(
                    ServerHost.host_ip == client_ip,
                    ServerHost.internal_ip == client_ip
                )
            ).limit(1)
        )
        
        host_name = result.scalar_one_or_none()
        if host_name:
            logger.info(f"IP验证通过: {client_ip} (主机: {host_name})")
            return True
        
        logger.warning(f"非法IP尝试访问: {client_ip}")
        return False
    
    @classmethod
    def get_file_path(cls, filename: str) -> str:
        """
        获取文件的完整路径
        """
        file_path = os.path.join(cls.AGENT_FILES_DIR, filename)
        if not os.path.exists(file_path):
            raise HTTPException(status_code=404, detail="文件不存在")
        return file_path

